﻿// Copyright 2004-2011 Castle Project - http://www.castleproject.org/
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#region 导入名称空间

using System;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security;

#endregion

namespace LightWork.DynamicProxy.Serialization
{
    [Serializable]
    public class RemotableInvocation : MarshalByRefObject, IInvocation, ISerializable
    {
        private readonly IInvocation parent;

        public RemotableInvocation(IInvocation parent)
        {
            this.parent = parent;
        }

        protected RemotableInvocation(SerializationInfo info, StreamingContext context)
        {
            parent = (IInvocation) info.GetValue("invocation", typeof(IInvocation));
        }

        public void SetArgumentValue(int index, object value)
        {
            parent.SetArgumentValue(index, value);
        }

        public object GetArgumentValue(int index)
        {
            return parent.GetArgumentValue(index);
        }

        public Type[] GenericArguments => parent.GenericArguments;

        /// <summary>
        /// </summary>
        /// <returns></returns>
        public void Proceed()
        {
            parent.Proceed();
        }

        public object Proxy => parent.Proxy;

        public object InvocationTarget => parent.InvocationTarget;

        public Type TargetType => parent.TargetType;

        public object[] Arguments => parent.Arguments;

        /// <summary>
        /// </summary>
        public MethodInfo Method => parent.Method;

        public MethodInfo GetConcreteMethod()
        {
            return parent.GetConcreteMethod();
        }

        /// <summary>
        /// For interface proxies, this will point to the
        /// <see cref="MethodInfo" /> on the target class
        /// </summary>
        public MethodInfo MethodInvocationTarget => parent.MethodInvocationTarget;

        public MethodInfo GetConcreteMethodInvocationTarget()
        {
            return parent.GetConcreteMethodInvocationTarget();
        }

        public object ReturnValue
        {
            get => parent.ReturnValue;
            set => parent.ReturnValue = value;
        }

        [SecurityCritical]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.SetType(typeof(RemotableInvocation));
            info.AddValue("invocation", new RemotableInvocation(this));
        }
    }
}